﻿using mozhi.smarterp.Business.Enums;
using mozhi.smarterp.Business.Sales.Repositories;
using mozhi.smarterp.Business.Sales.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;

namespace mozhi.smarterp.Business.Sales.Deliveries
{
    public class SaleDeliveryAppService : BusinessAppService, ISaleDeliveryAppService
    {
        private ISaleDeliveryRepository _repository;
        private SaleDeliveryManager _manager;

        public SaleDeliveryAppService(ISaleDeliveryRepository repository, SaleDeliveryManager manager)
        {
            _repository = repository;
            _manager = manager;
        }

        public async Task<SaleDeliveryDto> CreateAsync(SaleDeliveryCreateDto input)
        {
            var delivery = await _manager.GetAsync(null, input.CustomerId, input.Date, input.DepartmentId, input.WarehouseClerkId, input.CurrencyId, input.ExchangeRate, input.Comment);

            input.Items = input.Items ?? new List<SaleDeliveryItemCreateDto>();

            var deliveryItems = new List<SaleDeliveryItem>();

            foreach (var item in input.Items)
            {
                var deliveryItem = await _manager.GetItemAsync(null, item.ProductId, item.InventoryUnitId, item.OrderedQuantity, item.DeliveredQuantity, item.Price, null, item.WarehouseId, item.LocationId, item.BatchNumber,
                    item.SerialNumber, item.ProductionDate, item.Remark, item.IsGift);

                deliveryItems.Add(deliveryItem);
            }

            delivery.ChangeItems(deliveryItems);

            delivery = await _repository.InsertAsync(delivery);

            var result = ObjectMapper.Map<SaleDelivery, SaleDeliveryDto>(delivery);

            return result;
        }

        public Task DeleteAsync(Guid id)
        {
            throw new NotImplementedException();
        }

        public async Task<SaleDeliveryDto> GetAsync(Guid id)
        {
            var delivery = await _repository.GetAsync(id);

            var result = ObjectMapper.Map<SaleDelivery, SaleDeliveryDto>(delivery);

            return result;
        }

        public async Task<PagedResultDto<SaleDeliveryDto>> GetListAsync(SaleDeliveryPagedResultRequestDto filter)
        {
            var deliveries = await _repository.GetPagedListAsync(filter.Keyword, filter.Number, filter.CustomerId, filter.CurrencyId, filter.SkipCount, filter.MaxResultCount, filter.Sorting);

            var count = await _repository.GetCountAsync(filter.Keyword, filter.Number, filter.CustomerId, filter.CurrencyId, null);

            var items = ObjectMapper.Map<List<SaleDelivery>, List<SaleDeliveryDto>>(deliveries);

            return new PagedResultDto<SaleDeliveryDto>()
            {
                Items = items,
                TotalCount = count
            };
        }

        public async Task<SaleDeliveryDto> UpdateAsync(SaleDeliveryUpdateDto input)
        {
            var delivery = await _manager.GetAsync(input.Id, input.CustomerId, input.Date, input.DepartmentId, input.WarehouseClerkId, input.CurrencyId, input.ExchangeRate, input.Comment);

            input.Items = input.Items ?? new List<SaleDeliveryItemUpdateDto>();

            var deliveryItems = new List<SaleDeliveryItem>();

            foreach (var item in input.Items)
            {
                var deliveryItem = await _manager.GetItemAsync(input.Id, item.ProductId, item.InventoryUnitId, item.OrderedQuantity, item.DeliveredQuantity, item.Price, null, item.WarehouseId, item.LocationId, item.BatchNumber,
                    item.SerialNumber, item.ProductionDate, item.Remark, item.IsGift);

                deliveryItems.Add(deliveryItem);
            }

            delivery.ChangeItems(deliveryItems);

            delivery = await _repository.UpdateAsync(delivery);

            var result = ObjectMapper.Map<SaleDelivery, SaleDeliveryDto>(delivery);

            return result;
        }

        public Task<SaleDeliveryDto> UpdateStatusAsync(Guid id, DocumentStatusType status)
        {
            throw new NotImplementedException();
        }
    }
}
